// NodeJS.Timer nodejs中提供的，用于声明setTimeout类型
type Timer = NodeJS.Timer | null
// 定义回调函数，它接受的参数没办法进行约束，只能是any; void表示它没有返回值
type CallBack = (...args: any) => void

/**
 * 防抖函数
 * 严格来说，防抖函数不属于任何设计模式，它属于一种技巧设计，但如果强行归类，也可以把它归属到代理模式中
 * @param fun 回调函数，用于直实响应事件的方法
 * @param wait 防抖等待时间，未达到时间则认为这是一次事件抖动，忽略
 * @returns 返回一个可被调用的代理函数，我们的事件经过这个代理函数处理后才会被激活
 */
export function debounce(fun: CallBack, wait: number = 200) {
  // 定义timer的类型
  let timer: Timer
  // 它的参数也是属于无法被约束的，所以这里我们使用any
  return function (...args: any) {
    // 有新的请求进来就干掉原来的计时器，重新开始计时
    if (timer) {
      clearTimeout(timer)
    }

    // 计时器
    timer = setTimeout(() => {
      // 使用call或者apply的方式，执行当前闭包中缓存的事件函数，并将参数传出
      fun.apply(null, args)
    }, wait)
  }
}
